﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;

namespace OpenLS.Spreadsheet.Formats.Biff.Records
{
    internal class BigNameRecord : WorksheetLevelRecord
    {
        private string name;
        private byte[] rgbData;
        private int lcbData;

        internal override BiffRecordType RecordType
        {
            get { return BiffRecordType.BigName; }
        }

        private BigNameRecord(string name, byte [] data, int count)
        {
            this.name = name;
            this.rgbData = data;
            this.lcbData = count;
            Contract.Assert(rgbData.Length < 8225);
        }
        public static IEnumerable<BiffRecord> GetBigNameRecords (CustomProperty property)
        {
            byte[] data = property.Data;
            Func<int, int, byte[]> f = (start, count) =>
                                           {
                                               byte[] r = new byte[count];
                                               Array.Copy(data, start, r, 0, count);
                                               return r;
                                           };
            int len = Math.Min(8000 - property.Name.Length, data.Length);
            int index = 0;
            yield return new BigNameRecord(property.Name, f(index, len), data.Length);
            index += len;
            while (index < data.Length)
            {
                len = Math.Min(8000 , data.Length - index);
                yield return new ContinueBigNameRecord(f(index, len));
                index += len;

            }


        }

        public BigNameRecord()
        {
        }

        internal override void Apply(BiffReaderWorksheetContext context)
        {
            var following = this.GetFollowingRecords<ContinueBigNameRecord>();
            var followingBytes = Enumerable.SelectMany(following, f => f.Data);
            var allBytes = Enumerable.ToArray(Enumerable.Union(rgbData, followingBytes));
            Contract.Assert(allBytes.Length == this.lcbData);
            context.Worksheet.CustomProperties.Add(new CustomProperty(name, allBytes));
        }

        internal override void WriteContent(BiffWriterWorkbookContext context)
        {
            ushort reserved = 0x1000;
            context.Writer.Write(reserved);
            context.Writer.Write(lcbData);
            byte cbName = (byte) name.Length;
            context.Writer.Write(cbName);
            context.Write(XlEncodings.OneByteEncoding.GetBytes(name));
            context.Write(rgbData);
        }

        protected override void ReadContent(BiffReaderContext context, int length)
        {
            var reserved = context.ReadInt16();
            Contract.Assert(reserved == 0x1000);
            this.lcbData = context.ReadInt32();
            var cbName = context.ReadByte();
            var _rgbName = context.ReadBytes(cbName);
            this.name = XlEncodings.OneByteEncoding.GetString(_rgbName);
            this.rgbData = context.ReadBytes(length - cbName - 4 - 1- 2);
        }
    }
}